Web Q&A;: XML to HTML, Editable Dropdown List, Sending Large XML Files to SQL, Streaming Media, and More

MSDN Magazine

XML to HTML, Editable Dropdown List, Sending Large XML Files to SQL, Streaming Media, and More
Edited by Nancy Michell
Download the code for this article: Web0110.exe (36KB)
Browse the code for this article at Code Center: InsertCannedData

Q How can I get HTML code out of an XML document and into an HTML document? I have an XML document that looks like the following document:

  <foo>
  
<bar>
<comment>&lt;HTML&gt;&lt;BODY&gt;Hello,
World!&lt;/BODY&gt;&lt;/HTML&gt;
</Comment>
<![CDATA[<HTML>
<BODY>
Hello, World!
</BODY>
</HTML> ]]>
</bar>
</foo>

 

      I have the same HTML code in both a CDATA-SECTION and a regular text node. I'm using a transform to convert my XML file to an HTML document. However, no matter what I try, whenever I run the transform, the HTML code ends up with character entities rather than HTML tags, so the resulting document won't display correctly in the browser.

A
First, ask yourself if you really need the HTML to be in the XML. By default, the XML escapes output characters like < and >; that's why the HTML code ends up with character entities. One way around this is to put only data in the XML file and use XSL to provide the formatting you need. You can use XML as shown in Figure 1. Then load both documents into separate Document Object Model (DOM) objects and apply the transformation like this:

  HTML = XMLData.TransformNode(XSLData)
  

 

      One of the main purposes of XML technology is to separate data from formatting. HTML is a combination of both. You should design your solution so that XML and XSL will yield HTML (or XML or text).
      In some cases you will have the less-than and greater-than characters in an XML document; they can be output using the disable-output-escaping attribute on the xsl:value-of element. This feature is available in MSXML 3.0 or greater with the new namespace.

  <xsl:value-of select="/foo/bar" disable-output-escaping="yes" />
  

 

It's good practice to make the stylesheet output element specify HTML as the output method, like so:

  <xsl:output method='html' />
  

 

This can be used on <xsl:text disable-output-escaping='yes'> as well. See the XSLT recommendation at https://www.w3.org/TR/xslt.html#disable-output-escaping for more information.

Q
I used the following HTML to put a dropdown list with an edit feature on my Web page.

  <form>
  
<select name="sortby">
<option value="clientmachine">Client machine
<option value="suitedescription">Suite description
<option value="failures">Failures
<option value="status">Status
</select>
</form>

 

But this restricts the user's choice to one of the four options given. I would like the user to be able to enter his own value. Is there a simple way to do this?

A
There isn't a regular HTML control that has the editable combobox functionality you describe, so you'd actually have to write your control to be two controls tied together with events and use DHTML to populate the dropdown.

Figure 2 Radio Buttons
Figure 2 Radio Buttons

      You might want to consider a different approach using a radio button to toggle the selection, as shown in Figure 2. Then your ASP code will be based on the condition of the rdoOpt element (see Figure 3).

Q
I am working on a project which transfers XML data into a SQL database (see Figure 4). This works fine until I get an XML file which is bigger than 8KB—the maximum size for varchar. Can I use other types, or are there other ways to do this without pasting the whole XML file into the exec line? Can I simply reference the location of the XML file instead of the actual document?

A
The limitation is in the SQL Server™ 2000 engine and how it lets you use image/text/ntext in a stored procedure as a variable. You can use this data type as an input parameter, or use ODBC to round-trip from a text or image column using SQLGetData and SQLPutData. For a pure XML-to-SQL relational mapping (assuming you have a schema that can be made to support the SQL namespace) check out the Web Release 1 Bulk Load utility.
      If the XML data is passed as an argument from a client, you should use a stored procedure that you call with an ntext argument. Then you won't have an 8KB limit. See this month's code download for sample code for passing in large snippets of XML.

Q
I know it's easy to stream Windows Media™ files, but can I create a Web link to stream several small files seamlessly, as though they were all really one big file?

A
You'll find several articles on seamless stream switching on MSDN® Online. There is also a lot of information in the Windows Media Player SDK about this topic. Take a look at the following MSDN links for more information on the subject: https://msdn.microsoft.com/windowsmedia and https://msdn.microsoft.com/library/en-us/wmplay/mmp_sdk/ UsingWindowsMediaMetaFilesForSeamlessStreamSwitching.asp. The paper at this second link describes a process in which you send an OPENEVENT command 20 seconds or so before the last file finishes playing so that the next one is loaded and ready to go and the switch appears to be seamless.

Q
I am looking for scenarios that illustrate the use of images in XML. I also need to know exactly how they are represented in XML and what the schema for this looks like.

A
To represent images in XML, you have two options. The first is to encode the image data into valid XML, and pass it around inline with the XML document. Visio® 2002 and SQL Server 2000 both do this. In Visio, save as XML and then inspect the results. At the top you'll see an image preview encoded in base-64. In SQL Server, execute the query

  SELECT * FROM Employees FOR XML AUTO, BINARY BASE64
  

 

against the Northwind database and view the results as text. This keeps all the data together in one place (important for messaging or document storage), but takes more time and space to encode/decode the images.
      The second option is to store only metadata about the image in XML, and keep the original binary format outside (possibly referring to it using a relative path from the XML). In SQL Server, execute the query

  SELECT * FROM Employees FOR XML AUTO 
  

 

against Northwind. The image data is not encoded; instead, relative "dbobject" URLs are generated that point back to the image data in the database, which can then be retrieved without ever base-64 encoding. The same approach can be used with XML stored in file systems, as long as your referencing mechanism works (for example, if you use relative paths, you can't move files around relative to one another without breaking). This allows you to query over some aspects of the image (like size or keywords) without incurring the overhead of encoding it, but makes your system a little more fragile and adds other overhead (opening multiple files or connections to the database).

Q
I want to create an XML file from within my C++ app. I don't have a SQL or Microsoft® Access database where my data is located, so I use ADO, for example, to retrieve the data and work with this XML from there. Among the samples and articles in MSDN that deal with these scenarios, I didn't find a sample or doc to create the XML itself with some helper objects.
      I can put the XML syntax together myself, but I'm sure there is a way to use XMLDOM or some other COM objects to assist me in creating an XML file. I want to create an XML file from scratch (without any SQL or Access database). Is XMLDOM the way to go? If so, do you have an example for C++?
      It needs to be fast and memory efficient because the resulting XML files can be big. I heard that when using DOM, the whole document is handled in memory. Is there a way to flush the data from time to time?

A
The SAX2 Developer's Guide on MSDN says that the DOM allows you to create or modify a document in memory, as well as read a document from an XML source file. SAX (Simple API for XML) is designed for reading, not writing XML documents. The DOM is the better choice for modifying an XML document and saving the changed document to memory.
      Besides DOM, you may also want to look into SAX if you have large XML files. SAX is an alternative program model to DOM that is fast and memory efficient. The MSXML parser supports SAX since MSXML 3.0.
      One of the most efficient ways to create XML data is to use string concatenation, as opposed to the DOM (createElement and appendChild). Depending on whether you're looking for the easiest or fastest way, the MSXML SDK has a lot of C++ samples to choose from. For example, you can easily persist the ADO recordset as XML. See https://support.microsoft.com/default.aspx?scid=kb;en-us;q262450 for C++ and https://support.microsoft.com/default.aspx?scid=kb;en-us;q252767 for Visual Basic®. Also see Chris Lovett's article, "Inside XML Performance".

Q
While it's great that I can query my database using URLs, I've noticed that anyone in my organization can do the same. Is there a way to lock down requests and require the user to pass authentication information in the request? If I want to use "send clear text credential," how would I put that in the URL?

A
You have several mutually compatible options:

  • Use XPath/dbobject queries and XML Views to limit which data is exposed to the outside world. This way, you control what a URL query can access. Also, XPath and dbobject are read-only query languages.
  • Use templates to control which queries people can execute. Templates are parameterized, so you can pass whatever you want to them. (File permissions can also be used to control access to templates).
  • Set up Internet Information Services (IIS) permissions appropriately. Use the Configure SQL XML Support in IIS tool to do this. There are lots of security options here—Windows® integrated security, clear text passwords, and so on. You can create different virtual directories for different permission levels.
  • Set up database permissions appropriately using Enterprise Manager. In this way, you can limit the data users have access to, and the kinds of access they have (read-only, write-only, read/write, and so on). You'll definitely need to do this if you want to allow SQL queries in URLs.

      If you are looking at the API call in the documentation, you should be able to see the associated C++ sample showing how to request a document using this method.
      If you want to know how to get the response into an XML string, then as long as your server is setting the content-type to "text/xml" (as it should), then you will be able to grab the responseXML property from the same XMLHTTPRequest object you used to open the document. This returns an IDispatch pointer that references a DOMDocument. See the XML SDK for documentation on these properties and methods (https://msdn.microsoft.com/library/en-us/xmlsdk30/htm/xmobjpmeXMLhttpRequest.asp is a good place to start).

  HRESULT open(BSTR bstrMethod, BSTR bstrUrl, VARIANT bAsync, 
  
VARIANT bstrUser, VARIANT bstrPassword);

 

      This isn't special to SQL XML. The URL syntax is protocol://userID:password@example.com/path. Also, the APIs themselves may allow passing the user/password separate from the URL.
      Check out the extensive documentation on MSDN by searching for "URL authentication." Among the many hits, you should look at the examples at https://msdn.microsoft.com/library/en-us/xmlsdk30/htm/xmmthopenserverxmlhttp.asp.

Q
Using Windows Management Instrumentation (WMI), is there a way to ping a remote (Windows 2000- or Windows XP-based) system? I have written code that can do a simple IP ping, but this only tells me that the basic network services are running. Currently my code waits for a successful ping, then waits three minutes for each remote system to start all services. I am looking for a better WMI method to determine if a remote system is running.
      I need to do this so I won't have to wait for a DCOM connection timeout when I try to connect to a machine that isn't online. These take a lot longer. If it cannot be pinged with the ping provider, then there is no need to try to connect to it because the two machines involved cannot even shake hands over IP. An attempted DCOM connection would most likely fail.
      Once I have the query resultset, I can then execute the connectServer operation on each machine in the resultset.

A
Yes, you can do something like this in the root\cimv2 namespace using the ping provider included in Windows XP (see Figure 5). The statusCode being equal to zero means that the remote machine successfully replied to the request. The provider only supports getObject and ExecQuery. Note that this type of operation is only possible on Windows XP.

Send questions and comments to webqa@microsoft.com.

Thanks to the following Microsoft developers for their technical expertise: Joshua Allen, José Almeida, John Beck, Sander Bogdan, Michael Brundage, Affan Dar, Mark Davis, Cliff Don, Tom Fahrig, Julia Jia, Pranav Kandula, Aileen Lin, Andy Macourek, Scott McNairy, Andrew Minkin, Kevin Nixon, Neal Noble, Dare Obasanjo, Joe Orzech, Anoo Padte, Michael Peterson, Michael Rys, Andrew Simms, Don Smith, Guang-an Wu.


From the October 2001 issue of MSDN Magazine.